import ChartsConfig from "../config/ChartsConfig";
import { makeAutoObservable, } from "mobx";
import { OhlcData, OptionType, VolumeData } from "../models/ChartModels";

enum AnnotationType {
    line = "line",
    circle = 'circle',
    box = 'box',
}

class ChartStore {
    moreOptions: boolean = false;
    chart: any;
    seriesChartId: string = ChartsConfig?.ohlcId;
    iconMap: any = {};
    stockData: any = [];
    currentOptionId?: number;
    init: boolean = false;
    pending: boolean = true;
    fullScreen: boolean = false;
    stockTab: number = 1;
    rangeTab: number = 1;
    checkedPosition: string = '0';
    checkedRangePosition: string = '0';
    lineId?: number;
    private optionsId: Array<string> = [];
    private ohlcData: Array<OhlcData> = [];
    private volumeData: Array<VolumeData> = [];
    private year: number = 1;
    private yearMap: any = {};
    public annotationRange: Array<any> = [];
    popup?: any;

    constructor() {
        makeAutoObservable(this);
        setTimeout(() => {
            ChartsConfig.basicOptions.forEach((o) => {
                this.iconMap[o.id] = o.icon;
            })
            // ChartsConfig.options.forEach((o) => {
            //     this.iconMap[o.id] = o.icon;
            // })
        })

    }

    public async paintChart(data?: any) {
        console.log("paintChart paintChartpaintChart!!!!!!!");
        this.ohlcData = [];
        this.volumeData = [];
        var Highcharts: any = (window as any).Highcharts;
        if (data) {
            this.stockData = data;
        }
        if (this.stockData.length == 0) {
            return;
        }
        ChartsConfig.seriesType = 'candlestick';
        for (var i in this.stockData) {
            this.ohlcData.push(new OhlcData(this.stockData[i].time, this.stockData[i].open, this.stockData[i].high, this.stockData[i].low, this.stockData[i].close))
            this.volumeData.push(
                new VolumeData(
                    this.stockData[i].time,
                    this.stockData[i].volume,
                    this.stockData[i].open <= this.stockData[i].close ? "#227565" : "#cf4e63"
                )
            );
        }
        this.ohlcData.sort((a, b) => a.x - b.x);
        this.volumeData.sort((a, b) => a.x - b.x);
        Highcharts.setOptions(ChartsConfig.langOptions);
        Highcharts.dateFormat();
        this._calcYearRange();
        this.setRange(1);
    }

    showMore() {
        this.moreOptions = !this.moreOptions;
    }

    setChartId(id: string) {
        this.seriesChartId = id;
    }

    setCurrentOption(id: number) {

        if (this.currentOptionId === id) {
            this.currentOptionId = 0
            return;
        }
        this.currentOptionId = id;
    }

    addAnnotation(data: any, index: number) {
        if (this.optionsId.length > 0) {
            this.optionsId.forEach((id) => {
                this.chart.removeAnnotation(id);
                this.optionsId = [];
            })
        }
        if (index === this.lineId) {
            this.annotationRange = [];

            this.lineId = undefined;
            this.optionsId.forEach((id) => {
                this.chart.removeAnnotation(id);
                this.optionsId = [];
            })
            this.setRange();
            if (this.chart.resetZoomButton) {
                this.chart.resetZoomButton = this.chart.resetZoomButton.destroy();
            }
            return;
        } else {
            if (this.chart.resetZoomButton) {
                this.chart.resetZoomButton = this.chart.resetZoomButton.destroy();
            }
            this.lineId = index;
            var start = Date.parse(data['begin_date']);
            var end = Date.parse(data['end_date']);
            const range = 50;
            var previousDate: Array<number> = this.ohlcData.filter((d) => d.x < start).map((d) => d.x);
            var nextDate: Array<number> = this.ohlcData.filter((d) => d.x > end).map((d) => d.x);
            var minIdx = previousDate.length < range ? 0 : previousDate.length - range;
            var maxIdx = nextDate.length < range ? nextDate.length - 1 : range;
            this.setTabByDates(previousDate[minIdx]);
            this.chart.xAxis[0].setExtremes(previousDate[minIdx], nextDate[maxIdx]);
            this.annotationRange = [previousDate[minIdx], nextDate[maxIdx]];
        }

        var strategies = data['strategy_results'];
        strategies.forEach((s: any, i: number) => {
            this.drawAnnotation(s, i);
        });
    }

    removeAnnotation() {
        var annotations = this.chart.annotations.filter((a: any) => {
            return !a.options.id || a.options.id.indexOf("strategy") === -1;
        });
        if (annotations.length > 0) {
            var lastAnnotation = annotations[annotations.length - 1];
            this.chart.removeAnnotation(lastAnnotation);
        }
    }

    drawAnnotation(data: any, id: any) {
        var type = data['type'];
        var _points: Array<any> = JSON.parse(JSON.stringify(data['details']));
        var Highcharts: any = (window as any).Highcharts;
        var navigation = this.chart.options.navigation;
        _points.forEach((p) => p.x = Date.parse(p.x));
        var sId: string = 'strategy' + id;
        var option;
        if (type === AnnotationType.line) {
            option = {
                langKey: 'segment',
                type: 'crookedLine',
                id: sId,
                shapeOptions: {
                    strokeWidth: 2,
                },
                typeOptions: {
                    xAxis: 0,
                    yAxis: 0,
                    points: _points
                }
            };
        } else if (type === AnnotationType.box) {
            const interval: number = 43200000;
            var previousDates: Array<number> = this.ohlcData.filter((d) => d.x < _points[0].x).map((d) => d.x);
            var nextDates: Array<number> = this.ohlcData.filter((d) => d.x > _points[1].x).map((d) => d.x);
            var previousDate: number = previousDates[previousDates.length - 1];
            var nextDate: number = nextDates[0];
            var preDateCount = (_points[0].x - previousDate) / (2 * interval);
            var nextDateCount = (nextDate - _points[1].x) / (2 * interval);
            var maxY = Math.max(_points[0].y, _points[1].y);
            var distance = Math.abs(_points[0].y - _points[1].y) / 2;
            var calY = (y: number): number => {
                return y == maxY ? y + distance : y - distance;
            }
            option = {
                langKey: 'rectangle',
                type: 'basicAnnotation',
                id: sId,
                shapes: [{
                    type: 'path',
                    fill: 'rgba(85,157,233,0.2)',
                    stroke: '#559de9',
                    points: [
                        { xAxis: 0, yAxis: 0, x: _points[0].x - interval * preDateCount, y: calY(_points[0].y) },
                        { xAxis: 0, yAxis: 0, x: _points[0].x - interval * preDateCount, y: calY(_points[1].y) },
                        { xAxis: 0, yAxis: 0, x: _points[1].x + interval * nextDateCount, y: calY(_points[1].y) },
                        { xAxis: 0, yAxis: 0, x: _points[1].x + interval * nextDateCount, y: calY(_points[0].y) },
                        { xAxis: 0, yAxis: 0, x: _points[0].x - interval * preDateCount, y: calY(_points[0].y) },
                    ]
                }]
            };
        }
        var options = Highcharts.merge(option, navigation.annotationsOptions, navigation.bindings.segment.annotationsOptions);
        this.optionsId.push(sId);
        this.chart.addAnnotation(options);
    }


    drawCircle(x: number, y: number, r: number) {
        var Highcharts: any = (window as any).Highcharts;
        var navigation = this.chart.options.navigation;
        var options = Highcharts.merge({
            langKey: 'circle',
            type: 'basicAnnotation',
            shapes: [{
                type: 'circle',
                fill: 'purple',
                stroke: 'red',
                strokeWidth: 3,
                point: {
                    x: x,
                    y: y,
                    xAxis: 0,
                    yAxis: 0
                },
                r: r
            }]

        }, navigation.annotationsOptions, navigation.bindings.segment.annotationsOptions);
        this.chart.addAnnotation(options);
    }

    setRange(year?: number, useAnnotationRange?: boolean) {
        if (this.ohlcData.length === 0) {
            return;
        }
        if (this.chart && this.chart.resetZoomButton) {
            this.chart.resetZoomButton = this.chart.resetZoomButton.destroy();
        }
        if (year !== undefined) {
            this.year = year;
        }
        var Highcharts: any = (window as any).Highcharts;
        var _ohlcData: Array<OhlcData> = [];
        var _volumeData: Array<VolumeData> = [];
        if (this.year > 0) {
            var index = this.yearMap[this.year].index;
            _ohlcData = this.ohlcData.slice(index);
            _volumeData = this.volumeData.slice(index);
        } else {
            _ohlcData = this.ohlcData;
            _volumeData = this.volumeData;
        }
        var annotations: any[] = [];
        this.chart && this.chart.annotations && this.chart.annotations.forEach((a: any) => {
            annotations.push(a.options);
        });

        var options = [];
        if (this.chart && this.chart.series && this.chart.series.length > 2) {
            for (var i = 2; i < this.chart.series.length; i++) {
                var series = this.chart.series[i];
                if (series.userOptions.type !== 'column') {
                    options.push(series.userOptions);
                }

            }
        }
        this.chart = Highcharts.stockChart('container', ChartsConfig.setChart(_ohlcData, _volumeData));
        if (useAnnotationRange && this.annotationRange.length > 0) {
            this.chart.xAxis[0].setExtremes(this.annotationRange[0], this.annotationRange[1]);
        }
        annotations.forEach((a) => {
            this.chart.addAnnotation(a);
        })
        if (options.length > 0) {
            options.forEach((o) => {
                if (ChartsConfig.indicatorsWithAxes.indexOf(o.type) >= 0) {
                    var yAxis = this.chart.addAxis({
                        id: Highcharts.uniqueKey(),
                        offset: 0,
                        opposite: true,
                        title: {
                            text: ''
                        },
                        tickPixelInterval: 40,
                        showLastLabel: false,
                        gridLineColor: '#252525',
                        gridLineWidth: 0.5,
                        tickAmount: 3,
                        endOnTick: false,
                        labels: {
                            style: { "fontSize": "18px" },
                            align: 'left',
                            y: -2
                        }
                    }, false, false);
                    o.yAxis = yAxis.options.id;
                    this.chart.navigationBindings.resizeYAxes();
                }
                this.chart.addSeries(o, true);
            })
        }
    }

    private _calcRangeStartIdx(year: number): number {
        var now = this.ohlcData[this.ohlcData.length - 1].x;
        var yearDate = 31536000000 * year;
        var index: number = 0;
        for (var idx = this.ohlcData.length - 1; idx >= 0; idx--) {
            if (this.ohlcData[idx].x < now - yearDate) {
                index = idx - 1;
                break;
            }
        }
        return index;
    }

    onTypePicked(id: number, icon: string, type: OptionType) {
        var iconMap = this.iconMap;
        iconMap[id] = icon;
        this.iconMap = iconMap;
        if (ChartsConfig.annotationTypes.indexOf(type) > -1) {
            var crossHair = document.createElement("style");
            crossHair.setAttribute("id", 'crossHair');
            crossHair.type = "text/css";
            crossHair.innerHTML = ".highcharts-crosshair,.highcharts-crosshair-label{visibility:hidden}"
            var head = document.getElementsByTagName("head")[0];
            head.appendChild(crossHair);



        }
    }

    async changeTab(key: number, index: number) {
        var flutter_inappwebview = (window as any).flutter_inappwebview;
        if (key === 3) {
            if (flutter_inappwebview) {
                let canGo = await flutter_inappwebview.callHandler('verifyRecommenr');
                let isNull = !canGo && typeof canGo != "undefined" && canGo != 0
                if (!isNull) {
                    if (!canGo) return;
                }
            }
        } else if (key == 2) {
            if (flutter_inappwebview) {
                let canGo = await flutter_inappwebview.callHandler('verifyTechnic');
                let isNull = !canGo && typeof canGo != "undefined" && canGo != 0
                if (!isNull) {
                    if (!canGo) return;
                }
            }
        }
        this.stockTab = key;
        this.checkedPosition = ((100 / ChartsConfig.statisticTabs.length) * index) + '%';
    }

    setTabByDates(start: number) {
        var year = 0;
        const years: number[] = [1, 2, 3];
        console.log("start", new Date(start));
        for (var i = 0; i < years.length; i++) {
            console.log("?", new Date(this.yearMap[years[i]].date));
            if (start > this.yearMap[years[i]].date) {
                year = years[i];
                break;
            }
        }
        var index = (year - 1) >= 0 ? year - 1 : 3;
        console.log("year", year)
        this.changeRangeTab(year, index);
    }

    private _calcYearRange() {
        const years: number[] = [1, 2, 3];
        for (var i = 0; i < years.length; i++) {
            var idx = this._calcRangeStartIdx(years[i]);
            this.yearMap[years[i]] = { date: this.ohlcData[idx].x, index: idx };
        }
    }

    changeRangeTab(key: number, index: number) {
        this.rangeTab = key;
        this.checkedRangePosition = ((100 / ChartsConfig.rangeTabs.length) * index) + '%';
        if (!this.pending) {
            this.setRange(key);
        }
    }

    initState() {
        this.init = true;
        this.pending = true;
        this.changeTab(1, 0);
        this.changeRangeTab(1, 0);
        if (this.chart) {
            this.chart.destroy();
        }
    }
}

export default new ChartStore();